package com.tengju.bff.interfaces.app.charge.facade;

import com.idanchuang.income.ServiceIncome;
import com.tengju.bff.interfaces.app.charge.vo.MonthChargeChartVO;
import com.tengju.bff.interfaces.app.charge.vo.MonthChargeDetailVO;
import com.tengju.bff.interfaces.app.charge.vo.MonthChargeListVO;
import com.tengju.bff.interfaces.shared.Formatter;
import com.tengju.data.domain.model.report.AchievementBonusRepository;
import com.tengju.data.domain.model.report.AchievementBonusStatusEnum;
import com.tengju.data.domain.model.report.AchievementBonusSum;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.model.user.UserInfoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.tengju.bff.interfaces.app.charge.ChargeConstants.ACTIONS_NAMES;
import static java.math.RoundingMode.FLOOR;
import static java.math.RoundingMode.HALF_UP;

@Service
public class ChargeFacade {

    private final ServiceIncome serviceIncome;

    private final AchievementBonusRepository marketProfitRepository;

    private final UserInfoRepository userInfoRepository;


    @Autowired
    public ChargeFacade(ServiceIncome serviceIncome, AchievementBonusRepository marketProfitRepository,
                        UserInfoRepository userInfoRepository) {
        this.serviceIncome = serviceIncome;
        this.marketProfitRepository = marketProfitRepository;
        this.userInfoRepository = userInfoRepository;
    }


    public List<MonthChargeDetailVO> castMonth(UserIdCode idCode, String date, String amount) {

        Map<String, BigDecimal[]> data = serviceIncome.getUserMonthlyIncome(idCode.getValue(),
                YearMonth.parse(date),
                new BigDecimal(amount));

        return data.entrySet().stream()
                .map(bd -> {
                    String brandName = bd.getKey();
                    BigDecimal brandAmount = new BigDecimal("0");
                    List<MonthChargeDetailVO.Chargeline> chargelines = new ArrayList<>();
                    for (int i = 0; i < bd.getValue().length; i++) {
                        BigDecimal act = bd.getValue()[i];
                        String actionName = ACTIONS_NAMES[i];
                        brandAmount = brandAmount.add(act);
                        chargelines.add(
                                MonthChargeDetailVO.Chargeline.builder()
                                        .actionName(actionName)
                                        .amount(String.valueOf(act.setScale(2, HALF_UP)))
                                        .build()
                        );
                    }
                    return MonthChargeDetailVO.builder()
                            .brandName(brandName)
                            .chargelines(chargelines)
                            .amount(beautifyMoney(brandAmount.setScale(2, FLOOR).floatValue()))
                            .build();
                })
                .collect(Collectors.toList());
    }


    private String beautifyMoney(float yuan) {
        return String.format("%.2f 元", yuan);
    }

    public MonthChargeChartVO castLine(UserIdCode userIdCode, String year) {

        if (year == null) {
            return null;
        }

        UserInfo userInfo = userInfoRepository.getByIdCode(userIdCode);


        Map<Integer, AchievementBonusSum> bonusSumMap = initMonth(Integer.parseInt(year));

        List<AchievementBonusSum> bonuses = marketProfitRepository.sumByYear(
                new com.tengju.data.domain.model.user.UserIdCode(userIdCode.getValue()),
                LocalDate.parse(year + "-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        bonuses.forEach(bonus -> bonusSumMap.put(bonus.getMonth(), bonus));

        final Integer[] total = {0};
        final Integer[] max = {0};
        List<MonthChargeChartVO.Listline> listlines = new ArrayList<>();
        bonusSumMap.forEach((month, achievementBonus) -> {

            if(year.compareTo("2021") >= 0 && month >=1){
                if(!userInfo.showSettleData()){
                    return;
                }
            }

            int charge = achievementBonus.getProfit() == null ? 0 :
                    achievementBonus.getProfit().intValue() / 100 * 100;
            max[0] = Math.max(max[0], charge);
            total[0] = total[0] + charge;
            listlines.add(MonthChargeChartVO.Listline.builder()
                    .key(month % 100 + "月")
                    .value(String.valueOf(Math.max(0,charge)))
                    .build());
        });

        return MonthChargeChartVO.builder()
                .total(total[0].toString())
                .list(MonthChargeChartVO.ChargeList.builder()
                        .list(listlines)
                        .max(max[0].toString())
                        .build())
                .build();
    }

    public List<MonthChargeListVO> castList(UserIdCode userIdCode, String year) {
        List<MonthChargeListVO> list = new ArrayList<>();
        if (year == null) {
            return list;
        }

        UserInfo userInfo = userInfoRepository.getByIdCode(userIdCode);

        List<AchievementBonusSum> bonuses = marketProfitRepository.sumByYear(
                new com.tengju.data.domain.model.user.UserIdCode(userIdCode.getValue()),
                LocalDate.parse(year + "-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        Map<Integer, AchievementBonusSum> bonusSumMap = initMonth(Integer.parseInt(year));

        bonuses.forEach(bonus -> bonusSumMap.put(bonus.getMonth(), bonus));

        bonusSumMap.forEach((month, achievementBonus) -> {
            int achievement = Optional.ofNullable(achievementBonus.getAchievement())
                    .map(v -> Math.max(0,v.intValue()))
                    .map(val -> val / 100 * 100)
                    .orElse(0);
            int charge = Optional.ofNullable(achievementBonus.getProfit())
                    .map(v -> Math.max(0,v.intValue()))
                    .map(val -> val / 100 * 100)
                    .orElse(0);
            if (achievement == 0 && charge == 0) {
                return;
            }

            if(year.compareTo("2021") >= 0 && month >=1){
                if(!userInfo.showSettleData()){
                    return;
                }
            }

            String monthStr = String.valueOf(month);
            list.add(MonthChargeListVO.builder()
                    .achievement(Formatter.thousandMoneyOfTenMillion(achievement))
                    .profit(String.valueOf(charge))
                    .status(Optional.ofNullable(achievementBonus.getStatus())
                            .map(AchievementBonusStatusEnum::getStatus)
                            .orElse((byte) 0))
                    .month(monthStr.substring(0, 4) + "-" + monthStr.substring(4))
                    .noProfit(0)
                    .build());
        });

        // 月份倒序
        list.sort(Comparator.comparing(MonthChargeListVO::getMonth).reversed());
        return list;
    }

    private Map<Integer, AchievementBonusSum> initMonth(int year) {
        int tempYear = year * 100;

        Map<Integer, AchievementBonusSum> map = new TreeMap<>(Map.of(
                tempYear + 1, new AchievementBonusSum(),
                tempYear + 2, new AchievementBonusSum(),
                tempYear + 3, new AchievementBonusSum(),
                tempYear + 4, new AchievementBonusSum(),
                tempYear + 5, new AchievementBonusSum(),
                tempYear + 6, new AchievementBonusSum(),
                tempYear + 7, new AchievementBonusSum(),
                tempYear + 8, new AchievementBonusSum(),
                tempYear + 9, new AchievementBonusSum(),
                tempYear + 10, new AchievementBonusSum()
        ));
        map.put(tempYear + 11, new AchievementBonusSum());
        map.put(tempYear + 12, new AchievementBonusSum());
        return map;

    }



}
